import javax.swing.*;
import java.awt.*;

class Road extends JFrame {
    ICar LRcar, TBcar;
    TrafficCop tCop;

    Road() {
        setSize(400, 400);
        setVisible(true);
        setTitle("线程同步实例");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        tCop = new TrafficCop();
        LRcar = new ICar(tCop, ICar.leftToRight, 16);
        TBcar = new ICar(tCop, ICar.topToBotton, 17);
        start();
    }

    public void start() {
        LRcar.start();
        TBcar.start();

        while (true) {
            try {
                Thread.sleep(50);
            }
            catch(Exception e) {

            }

            repaint();
        }
    }

    public void paint(Graphics g) {
        super.paint(g);
        Color saveColor = g.getColor();
        g.setColor(Color.black);
        g.fillRect(0,  180,  400,  40);
        g.fillRect(180,  0,  40,  400);
        LRcar.drawCar(g);
        TBcar.drawCar(g);
    }
}

class ICar extends Thread {
    public int lastPos = -1;
    public int carPos = 0;
    public int speed = 10;
    public int direction = 1;
    public TrafficCop tCop;
    public final static int leftToRight = 1;
    public final static int topToBotton = 2;

    public ICar(TrafficCop tCop, int direction, int speed) {
        this.tCop = tCop;
        this.speed = speed;
        this.direction = direction;
    }

    public void run() {
        while (true) {
            tCop.checkAndGo(carPos, speed);
            carPos += speed;
            if (carPos >= 400) {
                carPos = 0;
            }

            try {
                Thread.sleep(200);
            }
            catch(InterruptedException e) {

            }
        }
    }

    public void drawCar(Graphics g) {
        if (direction == ICar.leftToRight) {
            g.setColor(Color.gray);
            g.fillOval(2 + carPos, 185, 10, 10);
            g.fillOval(26 + carPos, 185, 10, 10);
            g.fillOval(2 + carPos, 205, 10, 10);
            g.fillOval(26 + carPos, 205, 10, 10);
            g.setColor(Color.green);
            g.fillOval(0 + carPos, 190, 40, 20);
            lastPos = carPos;
        }
        else {
            g.setColor(Color.gray);
            g.fillOval(185, 2 + carPos, 10, 10);
            g.fillOval(185, 26 + carPos, 10, 10);
            g.fillOval(205, 2 + carPos, 10, 10);
            g.fillOval(205, 26 + carPos, 10, 10);
            g.setColor(Color.yellow);
            g.fillOval(190, 0 + carPos, 40, 20);
            lastPos = carPos;
        }
    }
}

class TrafficCop {
    private boolean IntersectionBusy = false;

    public synchronized void checkAndGo(int carPos, int speed) {
        if (carPos + 40 < 180 && carPos + 40 + speed >= 180 && carPos + speed <= 220) {
            while (IntersectionBusy) {
                try {
                    wait();
                }
                catch(InterruptedException e) {

                }
            }
            IntersectionBusy = true;
        }

        if (carPos + speed > 220) {
            IntersectionBusy = false;
        }

        notify();
    }
}

public class Test2 {
    public static void main(String[] args) {
        new Road();
    }
}
